package de.slothsoft.commons.swing;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Enumeration;

import javax.swing.DefaultListSelectionModel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;


public class JTableUtil {

    // TODO: API for jtable: empty row / count / sum / average

    public static final String COMMAND_MOUSE_CLICK = "mouseClick";
    public static final String COMMAND_KEY_PRESSED = "keyPressed";

    /**
     * Creates a table with a model, specific widths for it's columns and a
     * table cell renderer.
     * 
     * @param model
     *            - a model
     * @param columnWidths
     *            - the columns' widths
     * @param renderer
     *            - the renderer
     * @return the newly created table
     */

    public static <M extends TableModel> JTable createTable(M model, int[] columnWidths, TableCellRenderer renderer) {

	JTable table = new JTable();
	table.setModel(model);
	table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
	createRenderer(table, columnWidths, renderer);
	table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
	table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
	table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
	table.setRowSorter(new TableRowSorter<M>(model));

	return table;
    }

    /**
     * Creates a renderer for each column of the table.
     * 
     * @param table
     *            - the table
     * @param columnWidths
     *            - the columns' widths
     * @param renderer
     *            - the renderer
     */

    public static void createRenderer(JTable table, int[] columnWidths, TableCellRenderer renderer) {

	Enumeration<TableColumn> columns = table.getColumnModel().getColumns();
	int columnNumber = 0;
	while (columns.hasMoreElements()) {
	    TableColumn column = columns.nextElement();
	    column.setCellRenderer(renderer);

	    if (columnWidths != null) {
		setFixedColumnSize(column, columnWidths[columnNumber]);
	    }

	    column.setMinWidth(0);
	    column.setMaxWidth(1000);
	    columnNumber++;
	}
    }

    /**
     * Sets the size of a column to a fixed, not changeable value
     * 
     * @param column
     *            - the column
     * @param columnSize
     *            - the size of the column
     */

    public static void setFixedColumnSize(TableColumn column, int columnSize) {
	column.setWidth(columnSize);
	column.setMinWidth(columnSize);
	column.setMaxWidth(columnSize);
    }

    /**
     * Adds a selection listener to a table - e.g. a mouse listener and a key
     * listener.
     * 
     * @param table
     *            - the table to be added to
     * @param listener
     *            - the listener to be added
     */

    public static void addSelectionListener(final JTable table, final ActionListener listener) {
	if (listener == null)
	    return;
	table.addMouseListener(new MouseAdapter() {
	    @Override
	    public void mouseClicked(MouseEvent e) {
		ActionEvent event = new ActionEvent(e.getSource(), e.getID(), COMMAND_MOUSE_CLICK);
		listener.actionPerformed(event);
	    }
	});
	table.addKeyListener(new KeyAdapter() {
	    @Override
	    public void keyTyped(KeyEvent e) {
		ActionEvent event = new ActionEvent(e.getSource(), e.getID(), COMMAND_KEY_PRESSED);
		listener.actionPerformed(event);
	    }
	});
    }

    /**
     * Returns the selected element of a JTable.
     * 
     * @return one element or null
     */

    public static <T> T getSelectedElement(JTable table, AbstractListTableModel<T> model) {
	int selected = table.getSelectedRow();
	if (selected != -1) {
	    int modelIndex = table.getRowSorter().convertRowIndexToModel(selected);
	    return model.getList().get(modelIndex);
	}
	return null;
    }

    private JTableUtil() {
	// RUN YOU FOOLS!!!
    }
}
